﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media.Imaging;
using Log;
using SmileSolver;
using Solver.ModelView;

namespace Solver
{
    public class SolutionGroup : AbstractViewModel, ISolutionTask
    {
        ILogger _log;
        SolutionCombination _start;
        int _count;
        int _processed = 0;
        static int global = 0;

        public SolutionGroup(List<SolutionCombination> array, ILogger log)
        {
            _log = log;
            Init(array);
            Name = "Group " + (global++).ToString();
        }

        ~SolutionGroup()
        {
            //int a = 0;
        }

        private void Init(List<SolutionCombination> array)
        {
            _count = array.Count;
            foreach (SolutionCombination sc in array)
            {
                ISolutionTask task = GetTask(sc, typeof(SolutionCrossTask));
                _list.Add(task);
            }
        }

        public ISolutionTask GetTask(SolutionCombination combination, Type typ)
        {
            if (typ == typeof(SolutionCrossTask))
            {
                SolutionCrossTask solution = new SolutionCrossTask(_log);
                solution.Name = "Solution - " + combination.ID;// ID = poradi kombinace
                solution.OnComplete += solution_OnComplete;
                solution.FirstCombination(new SolutionCombination(combination));
                return solution;
            }

            // nevim cim resit
            return null;
        }

        void solution_OnComplete(ISolutionTask task)
        {
            _processed++;
            double proc = 100 * (double)_processed / (double)_count;
            if (((int)proc % 2) == 0)
            {
                this.Progress = (int)proc;
            }

            if (OnComplete != null)
            {
                if (task.Success == true)
                {
                    task.OnComplete -= this.solution_OnComplete;
                    OnComplete.BeginInvoke(task,null,null);
                }
                else if (_processed == _count)
                {
                    task.OnComplete -= this.solution_OnComplete;
                    OnComplete(this);
                }
            }
        }


        List<ISolutionTask> _list=new List<ISolutionTask>();
        public void Start()
        {
            Task task = new Task(new Action(() =>
            {
                    lock (_list)
                    {
                        foreach (ISolutionTask t in _list)
                        {
                            try
                            {
                                t.Start();
                            }
                            catch (Exception e)
                            {
                                _log.Error(e.Message, "SolutionGroup.Start");
                            }
                        }
                    }

                    Clear();
           }));            
           task.Start();
        }

        public void FirstCombination(SolutionCombination start)
        {
            _start = start;
        }

        public void Clear()
        {
            lock (_list)
            {
                foreach (SolutionCrossTask st in _list)
                {
                    st.Clear();
                }
                _list.Clear();
            }
        }

        public event SmileSolver.CompleteTaskHandler OnComplete;
        //PROPERTIES
        public SolutionCombination Combination { get { return _start; } }


        private int _progress = 0;
        public int Progress
        {
            get { return _progress; }
            set
            {
                _progress = value;
                OnPropertyChanged("Progress");
            }
        }

        TaskState _state = TaskState.Stop;
        public TaskState State
        {
            get { return _state; }
            set
            {
                _state = value;
                OnPropertyChanged("State");
                OnPropertyChanged("StateImage");
                OnPropertyChanged("IsVisible");
            }
        }

        BitmapSource _source;
        public BitmapSource StateImage
        {
            get
            {
                if (_source != null)
                    _source.Freeze();

                if (_state == TaskState.Play)
                {
                    // Create source.
                    BitmapImage bi = new BitmapImage();                    
                    bi.BeginInit();
                    bi.UriSource = new Uri(@"/Solver;component/Images/play.png", UriKind.RelativeOrAbsolute);
                    bi.EndInit();
                    _source = bi;
                    return bi;
                }
                else if (_state == TaskState.Stop)
                {
                    BitmapImage bi = new BitmapImage();                    
                    bi.BeginInit();
                    bi.UriSource = new Uri(@"/Solver;component/Images/stop.png", UriKind.RelativeOrAbsolute);
                    bi.EndInit();
                    _source = bi;
                    return bi;
                }
                else if (_state == TaskState.End)
                {
                    BitmapImage bi = new BitmapImage();                    
                    bi.BeginInit();
                    bi.UriSource = new Uri(@"/Solver;component/Images/finish.png", UriKind.RelativeOrAbsolute);
                    bi.EndInit();
                    _source = bi;
                    return bi;
                }
                else
                {
                    BitmapImage bi = new BitmapImage();
                    bi.BeginInit();
                    bi.UriSource = new Uri(@"/Solver;component/Images/finish.png", UriKind.RelativeOrAbsolute);
                    bi.EndInit();
                    _source = bi;
                    return bi;
                }
 
            }
        }

        public string Name
        {
            get;
            set;
        }

        private SolutionCombination _solution = null;
        public SolutionCombination Solution
        {
            get { return _solution; }
            set
            {
                _solution = value;
                OnPropertyChanged("Solution");
                OnPropertyChanged("SolutionString");
            }
        }

        public string SolutionString
        {
            get
            {
                if (_solution == null)
                    return "";

                return _solution.ToString();
            }
        }

        private bool _success = false;
        public bool Success
        {
            get { return _success; }
            set
            {
                _success = value;
                OnPropertyChanged("Success");
            }
        }

        public Visibility IsVisible
        {
            get
            {
                return Visibility.Visible;
            }
        }
    }
}
